#pragma once

#include "PillboxCollider.h"
#include "SimManager.h"
#include "NeuralNetFourLayers.h"
#include "NeuralNetThreeLayers.h"
#include "NeuralNetTwoLayers.h"

class Robot
{
	// PillboxCollider m_simulation.AccessCollider();
	SimManager m_simulation;
	
	double m_arrPos2dBackPoints[400][2];
	double m_arrPos2dFrontPoints[400][2];
	double m_arrPos2dDir[400][2];
	double m_arrLfPrevColors[400][3];

	int m_nTrainLength;

	double m_arrLfColor[3];

	int PushBotOntoTrail();
public:
	Robot(void);
	Robot(double lfLength, double lfWidth, double lfXPos, double lfYPos, double lfTheta); 
	~Robot(void);

	inline void ClearTrails() { m_nTrainLength = 0; }

	void SetColor(double lfRed, double lfGreen, double lfBlue)
	{
		m_arrLfColor[0] = lfRed; m_arrLfColor[1] = lfGreen; m_arrLfColor[2] = lfBlue;
	}

	void SetAllObstacleParams(int nNumObstacles, int nNumSides, Pos2d p2ObstacleMin, Pos2d p2ObstacleMax, double lfObstacleRad);

	void SetRobotAndGoal();

	bool Move(int nTurnAmount, int nSpeed);

	void DrawMe();

	void TrainOnce(double lfActionSelectionBias, double lfCollisionPunishment,
		double lfTrainRate, double lfDiscountFactor)
	{
		m_simulation.TrainOnce(lfActionSelectionBias, lfActionSelectionBias, lfCollisionPunishment, lfTrainRate, lfDiscountFactor);
	}

	bool RunRobotOneStep(bool & bHitGoal)
	{
		bool bResult = m_simulation.RunRobotOneStep(bHitGoal);
		m_arrLfColor[1] = m_simulation.GetMostRecentGoodness();
		PushBotOntoTrail();
		return bResult;
	}

	void SetQlearnState(bool bQlearn)
	{
		m_simulation.SetUseQlearnOnly(bQlearn);
	}

	inline void SetMagicAnneal(double lfMagic) { m_simulation.SetMagicAnneal(lfMagic); }
	inline double GetMagicAnneal() const { return m_simulation.GetMagicAnneal(); }

	void Train(int nTimes, const char * szFileOut, int nEvalFreq, double lfLearningRate, double lfDiscountFactor);

	void SaveNeuralNet(const char * szFiOut)
	{
		m_simulation.SaveNeuralNet(szFiOut);
	}

	void LoadNeuralNet(const char * szFiIn)
	{
		m_simulation.LoadNeuralNet(szFiIn);
	}
};
